<?php

/**
 *
 * @author ben <ben@spicatech.cn>  Created on 2015-11-9
 */
abstract class I18nBaseActiveRecord extends ProjectActiveRecord {

    const DEFAULT_LANG = 'zh_cn';
    const LANG_ZH_CN = 'zh_cn';
    const LANG_ZH_HK = 'zh_hk';
    const LANG_ZH_TW = 'zh_tw';
    const LANG_EN_US = 'en_us';

    protected $_lang = '';

    abstract public function i18nFields();

    abstract public function i18nMapModel();

    /**
     * 
     * @return type
     */
    public static function getALangList() {
        return [
            self::LANG_ZH_CN,
            self::LANG_ZH_HK,
            self::LANG_ZH_TW,
            self::LANG_EN_US
        ];
    }

    /**
     * 
     * @param type $lang
     */
    public function setLang($lang) {
        $_lang = strtolower(str_replace('-', '_', $lang));
        $list = self::getALangList();
        if (!in_array($_lang, $list)) {
            $lang = self::DEFAULT_LANG;
        }
        $this->_lang = $_lang;
    }

    /**
     * 
     */
    public function initI18nModel($lang = self::DEFAULT_LANG) {
        $this->setLang($lang);
        if ($this->isDefaultLang()) {
            return true;
        }
        $fields = $this->i18nFields();
        foreach ($fields as $k => $v) {
            $this->$v = $this->getFieldContent($v);
        }
    }

    /**
     * 
     * @return type
     */
    public function saveI18nModel() {
        if ($this->isDefaultLang()) {
            return $this->save();
        }
        $attr = $this->getAttributes();
        $fiels = $this->i18nFields();
        foreach ($fiels as $field) {
            $this->saveField($field, $attr[$field]);
            unset($attr[$field]);
        }

        return $this->save($attr);
    }

    /**
     * 
     * @return type
     */
    public function isDefaultLang() {
        return $this->_lang == self::DEFAULT_LANG;
    }

    /**
     * 
     * @param type $field
     * @return type
     */
    public function getFieldContent($field) {
        $model = $this->findI18nModel($field);
        return $model ? $model->content : '';
    }

    /**
     * 
     * @param type $field
     * @return type
     */
    public function findI18nModel($field) {
        $map = $this->i18nMapModel();
        $_pk = $this->primaryKey;
        $condition = 'refer_table = :tb and refer_field = :field and refer_id = :id and lang = :lang';
        $params = [
            ':tb' => $this->tableName(),
            ':field' => $field,
            ':lang' => $this->_lang,
            ':id' => $_pk
        ];
        $model = $map->find($condition, $params);
        return $model;
    }

    /**
     * 
     * @param type $field
     * @param type $content
     * @return type
     */
    public function saveField($field, $content) {
        $model = $this->findI18nModel($field);
        if (!$model) {
            $model = $this->i18nMapModel();
        }
        $model->refer_table = $this->tableName();
        $model->refer_field = $field;
        $model->refer_id = $this->primaryKey;
        $model->lang = $this->_lang;
        $model->content = $content;
        if (!$model->save()) {
            
        }
        return true;
    }

    /**
     * 
     * @param I18nBaseActiveRecord $model
     * @param array $fields
     * @param type $pk
     * @return type
     */
    public function getContentMapByFields(I18nBaseActiveRecord $model, array $fields, $pk) {
        if ($model->isDefaultLang()) {
            return [];
        }
        $table = $model->tableName();
        $i18n = $model->i18nMapModel();
        $f = implode(',', array_map(function($item) {
                    return "'" . $item . "'";
                }, $fields));
        $condition = "refer_table = :refer_table and refer_field in({$f}) and refer_id = :refer_id and lang = :lang";
        $params = [
            ':refer_table' => $table,
            ':refer_id' => $pk,
            ':lang' => $this->_lang
        ];
        $list = $i18n->findAll($condition, $params);

        $map = [];
        foreach ($list as $k => $v) {
            $map[$v->refer_field] = $v->content;
        }
        foreach ($fields as $f) {
            if (!isset($map[$f])) {
                $map[$f] = '';
            }
        }
        return $map;
    }

    /**
     * 
     * @param array $list
     * @param I18nBaseActiveRecord $model
     * @param type $pkField
     */
    public static function initI18nList(array &$list, I18nBaseActiveRecord $model, $pkField = 'id') {
        $fields = $model->i18nFields();
        foreach ($list as $k => $v) {
            $contens = $model->getContentMapByFields($model, $fields, $v[$pkField]);
            $v = array_merge($v, $contens);
            $list[$k] = $v;
        }
    }

}
